﻿package com.sff.system {
	
	import com.sff.core.sff_internal;
	import com.sff.events.ModuleEvent;
	import com.sff.manager.DataManager;
	import com.sff.manager.LayerManager;
	import com.sff.manager.LoaderManager;
	import com.sff.manager.ResizeManager;
	import com.sff.manager.SoundManager;
	import com.sff.manager.StyleManager;
	import com.sff.module.Module;
	import com.sff.module.ModuleLoader;
	import com.sff.module.ModuleLoaderFactory;
	import com.sff.site.tree.Tree;
	
	import flash.events.Event;
	import flash.geom.Rectangle;
	
	public class ModuleSystem {
		
		protected var _dataMgr 				: DataManager;
		protected var _styleMgr				: StyleManager;
		protected var _resizeMgr 			: ResizeManager;
		protected var _loaderMgr			: LoaderManager;
		protected var _soundMgr				: SoundManager;
		protected var _layerMgr				: LayerManager;
		
		protected var _resizeChilds 		: Boolean = false;
		protected var _moduleLoaderFactory 	: ModuleLoaderFactory;		
		protected var _module 				: Module;
		
		public function ModuleSystem(data : DataManager, style:StyleManager, module : Module ) {
			build(data, style, module );
		}
		
		public function get module() : Module {
			return _module;
		}
		
		public function get siteManager(): Tree {
			return _dataMgr.sff_internal::tree;
		}
		
		public function get dataManager(): DataManager {
			return _dataMgr;
		}
		
		public function get styleManager(): StyleManager {
			return _styleMgr;
		}	
				
		public function get resizeManager() : ResizeManager {
			return _resizeMgr;
		}
		
		public function get loaderManager(): LoaderManager {
			return _loaderMgr;
		}
		
		public function get layerManager():LayerManager {
			return _layerMgr;
		}
		
		public function get soundManager(): SoundManager {
			return _soundMgr;
		}
		
		public function getModuleLoader() : ModuleLoader {
			return _moduleLoaderFactory.getModuleLoader();
		}
				
		public function dispose() : void {
			_loaderMgr.dispose();
			_loaderMgr = null;
			
			unregisterResizeManager( );
			_resizeMgr = null;
			
			_dataMgr.dispose( );
			_dataMgr = null;
			
			_soundMgr.dispose();
			_soundMgr = null;
			
			unregisterModuleLoaderFactory();
			_moduleLoaderFactory.dispose();
			_moduleLoaderFactory = null;
			
			_module = null;
		}

		protected function build(data : DataManager, style:StyleManager, module : Module ) : void {
			_module = module;
			_dataMgr = data;
			_styleMgr = style;
			
			_resizeMgr 	= new ResizeManager( );
			registerResizeManager();
			
			_loaderMgr = new LoaderManager();
			_loaderMgr.execute();
			
			_layerMgr = new LayerManager(_resizeMgr);
			
			_soundMgr = new SoundManager();
			
			_moduleLoaderFactory = new ModuleLoaderFactory( _module );			
			registerModuleLoaderFactory();
		}
		
		sff_internal function _scan() : void {
			_moduleLoaderFactory.scan();
		}
		
		sff_internal function _willDraw( flag : Boolean ) : void {
			_module.dispatchEvent( new ModuleEvent( flag ? ModuleEvent.DRAWING : ModuleEvent.DRAWING, _module ) );
			
			var arrChilds:Array = _moduleLoaderFactory.modules;
			for (var i:int = 0; i < arrChilds.length; i ++) {
				Module(arrChilds[i]).system.sff_internal::_willDraw( flag );
			}			
		}

		protected function registerResizeManager() : void {
			resizeManager.addEventListener( Event.RESIZE, onResizeHandler);
		}

		protected function unregisterResizeManager() : void {
			resizeManager.removeEventListener( Event.RESIZE, onResizeHandler );
		}
				
		protected function registerModuleLoaderFactory() : void {
			_moduleLoaderFactory.addEventListener( ModuleEvent.ADDED , onModuleAddedHandler);
			_moduleLoaderFactory.addEventListener( ModuleEvent.REMOVED , onModuleRemovedHandler);
		}
		
		protected function unregisterModuleLoaderFactory() : void {
			_moduleLoaderFactory.dispose();
			_moduleLoaderFactory.removeEventListener( ModuleEvent.ADDED , onModuleAddedHandler );
			_moduleLoaderFactory.removeEventListener( ModuleEvent.REMOVED , onModuleRemovedHandler );
		}
		
		private function onModuleAddedHandler(evt : ModuleEvent) : void {
			var child : Module = evt.module;
			if( _moduleLoaderFactory.contains( child ) ) {
				addChild( child );
			}
			
			if( evt.mbubble ) { 
				_module.dispatchEvent( evt );
			}	
		}
		
		private function onModuleRemovedHandler(evt : ModuleEvent) : void {
			var child : Module = evt.module;
			if( _moduleLoaderFactory.contains( child ) ) {
				removeChild( child );
				_moduleLoaderFactory.removeModule(child );
			}
			
			if( evt.mbubble ) {
				_module.dispatchEvent( evt );
			}	
		}

		private function addChild(child : Module ) : void {
			child.system.resizeManager.addEventListener(Event.RESIZE, onChildResizeHandler);
			child.system.resizeManager.sff_internal::setTransform( resizeManager.sff_internal::getTransform() );
			
			child.sff_internal::_run();
			child.system.resizeManager.change();
		}
		
		private function removeChild( child : Module ) : void {
			child.system.resizeManager.removeEventListener(Event.RESIZE, onChildResizeHandler);
		}
				
		private function onChildResizeHandler(event : Event) : void {
			resizeManager.dispatchEvent( new Event(ModuleEvent.CHILD_RESIZE) );
			
			if(!_resizeChilds ) {
				onResizeHandler(null);
			}
		}
		
		private function onResizeHandler(evt: Event ) : void {
			
			var transform : Rectangle = resizeManager.sff_internal::getTransform();
			_resizeChilds = true;
			
			var arrChilds:Array = _moduleLoaderFactory.modules;
			for (var i:int = 0; i < arrChilds.length; i ++) {
				Module(arrChilds[i]).system.resizeManager.sff_internal::setTransform( transform );
			}
			
			_resizeChilds = false;
		}		
	}
}